Fric-frac model binding Person 1 op 1
In deze les leren we hoe je het model aanpast voor een property die een foreign-key is. Uitleg hierover vind je op Relationships (10/27/2016). Een praktisch voorbeeld: Saineshwar Bageri, Binding Dropdown List With Database In ASP.NET Core MVC, Dec 12 2016
Probleem
In de tabel Person
zit er een kolom met een foreign-key, namelijk CountryId
verwijst naar de Country
tabel.
- In het model hebben we dus een lijst van alle landen nodig zodat we die in een keuzelijst in de view kunnen tonen.
- In de
ReadingOne
moeten we deName
van het land tonen en niet deId
.
Oplossing
- In de Person/ReadingOne view willen we de naam van het land tonen en niet de Id:
- We passen het model aan. We voegen een property toe om de info over het land bij te houden:
using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace FricFrac.Models.FricFrac { public partial class Person { public Person() { } [Required] [StringLength(50)] [FromForm(Name = "Person-FirstName")] public string FirstName { get; set; } [Required] [StringLength(120)] [FromForm(Name = "Person-LastName")] public string LastName { get; set; } [StringLength(255)] [FromForm(Name = "Person-Email")] public string Email { get; set; } [StringLength(255)] public string Password { get; set; } [StringLength(255)] [FromForm(Name = "Person-Address1")] public string Address1 { get; set; } [StringLength(255)] [FromForm(Name = "Person-Address2")] public string Address2 { get; set; } [StringLength(20)] [FromForm(Name = "Person-PostalCode")] public string PostalCode { get; set; } [StringLength(80)] [FromForm(Name = "Person-City")] public string City { get; set; } [Required] [Column(TypeName = "int(11)")] [FromForm(Name = "Person-CountryId")] public int? CountryId { get; set; } [StringLength(25)] [FromForm(Name = "Person-Phone1")] public string Phone1 { get; set; } [Column(TypeName = "datetime")] [FromForm(Name = "Person-Birthday")] public DateTime? Birthday { get; set; } [Column(TypeName = "int(11)")] [FromForm(Name = "Person-Rating")] public int? Rating { get; set; } [FromForm(Name = "Person-Id")] [Column(TypeName = "int(11)")] public int Id { get; set; } [ForeignKey("CountryId")] public Country Country { get; set; } } }
- De namen van de landen bevatten Latijnse karakters zoals é, è enz. Om die correct uit de database in te lezen moeten we het model van
Country
aanpassen. Daarvoor heb je deMySql.Data.EntityFrameworkCore.DataAnnotations
namespace nodig (MySQL Configuring Character Sets and Collations in EF Core):using Microsoft.AspNetCore.Mvc; using MySql.Data.EntityFrameworkCore.DataAnnotations; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace FricFrac.Models.FricFrac { public partial class Country { public Country() { } [Required] [StringLength(50)] [MySqlCharset("latin1")] [FromForm(Name = "Country-Name")] public string Name { get; set; } [Required] [StringLength(2)] [FromForm(Name = "Country-Code")] public string Code { get; set; } [Column(TypeName = "int(11)")] [FromForm(Name = "Country-Id")] public int Id { get; set; } [FromForm(Name = "Country-Desc")] [StringLength(256)] public string Desc { get; set; } } }
- In de
ReadingOne
methode van dePersonController
zoeken we de gegevens van de persoon op lezen we de gegevens van het land in en geven het model door aan de view:[HttpGet] public IActionResult ReadingOne(int? id) { ViewBag.Message = "Lees een Persoon in de database"; if (id == null) { return NotFound(); } var person = dbContext.Person.SingleOrDefault(m => m.Id == id); if (person == null) { return NotFound(); } person.Country = dbContext.Country.SingleOrDefault(m => m.Id == person.CountryId); return View(person); }
- In de
ReadingOne
view vanPerson
passen vangen we het model op en tonen de gegevens van de persoon in de HTML:@model FricFrac.Models.FricFrac.Person @{ Layout = "~/Views/Shared/MasterLayout.cshtml"; } <div class="control-panel"> <a href="/Home/Index" class="tile _14x1"> <span class="icon-menu2"></span> <span class="screen-reader-text">Home</span> </a> <h1>Fric-frac</h1> </div> <form class="show-room entity" action="/Person/Index" method="post"> <div class="detail"> <div class="command-panel"> <h2 class="banner">Persoon</h2> <a href="/Person/UpdatingOne/@Model.Id" class="tile"> <span class="icon-pencil"></span> <span class="screen-reader-text">Updating One</span> </a> <a href="/Person/InsertingOne" class="tile"> <span class="icon-plus"></span> <span class="screen-reader-text">Inserting One</span> </a> <a href="/Person/DeleteOne/@Model.Id" class="tile"> <span class="icon-remove"></span> <span class="screen-reader-text">Delete One</span> </a> <a href="/Person/Cancel" class="tile"> <span class="icon-close"></span> <span class="screen-reader-text">Annuleren</span> </a> </div> <fieldset> <div> <label for="Person-FirstName">Voornaam</label> <span>@Model.FirstName</span> </div> <div> <label for="Person-LastName">Familienaam</label> <span>@Model.LastName</span> </div> <div> <label for="Person-Email">E-mail</label> <span>@Model.Email</span> </div> <div> <label for="Person-Address1">Adres 1</label> <span>@Model.Address1</span> </div> <div> <label for="Person-Address2">Adres 2</label> <span>@Model.Address2</span> </div> <div> <label for="Person-PostalCode">Postcode</label> <span>@Model.PostalCode</span> </div> <div> <label for="Person-City">Stad</label> <span>@Model.City</span> </div> <div> <label for="Person-Country">Land</label> <span>@Model.Country.Name</span> </div> <div> <label for="Person-Phone1">Telefoon</label> <span>@Model.Phone1</span> </div> <div> <label for="Person-Birthday">Geboortedatum</label> <span>@Model.Birthday</span> </div> </fieldset> <div class="feedback"></div> </div> <aside class="list"> <table></table> </aside> </form>
- We passen het model aan. We voegen een property toe om de info over het land bij te houden:
- In de
InsertingOne
view willen we de lijst van de landen tonen in de naam van het opgegeven land in de keuzelijst tonen:- In de
InsertingOne
methode van dePersonController
lezen we landen in en geven die aan de view door met behulp van deViewbag
:public IActionResult InsertingOne() { ViewBag.Title = "Fric-frac Person Inserting One"; ViewBag.Countries = dbContext.Country.ToList(); return View(); }
- We passen de
Person/InsertingOne
view aan en lezen deoption
elementen uit deCountries
lijst:@{ Layout = "~/Views/Shared/MasterLayout.cshtml"; } <nav class="control-panel"> <a href="/Home/Index" class="tile"> <span class="icon-menu2"></span> <span class="screen-reader-text">Home</span> </a> <h1 class="banner">Fric-frac</h1> </nav> <form class="show-room entity" action="/Person/InsertOne" method="post"> <div class="detail"> <div class="command-panel"> <h2 class="banner">Persoon</h2> <button type="submit" value="/Person/InsertOne" class="tile"> <span class="icon-disk"></span> <span class="screen-reader-text">Insert One</span> </button> <a href="/Person/Cancel" class="tile"> <span class="icon-close"></span> <span class="screen-reader-text">Annuleren</span> </a> </div> <fieldset> <div> <label for="Person-FirstName">Voornaam</label> <input id="Person-FirstName" name="Person-FirstName" type="text" value="" required /> </div> <div> <label for="Person-LastName">Familienaam</label> <input id="Person-LastName" name="Person-LastName" type="text" value="" required /> </div> <div> <label for="Person-Email">E-mail</label> <input id="Person-Email" name="Person-Email" type="email" value="" /> </div> <div> <label for="Person-Address1">Adres 1</label> <input id="Person-Address1" name="Person-Address1" type="text" value="" /> </div> <div> <label for="Person-Address2">Adres 2</label> <input id="Person-Address2" name="Person-Address2" type="text" value="" /> </div> <div> <label for="Person-PostalCode">Postcode</label> <input id="Person-PostalCode" name="Person-PostalCode" type="text" value="" /> </div> <div> <label for="Person-City">Stad</label> <input id="Person-City" name="Person-City" type="text" value="" /> </div> <div> <label for="Person-CountryId">Land</label> <select id="Person-CountryId" name="Person-CountryId"> @foreach (var item in ViewBag.Countries) { <option value="@item.Id">@item.Name</option> } </select> </div> <div> <label for="Person-Phone1">Telefoon</label> <input id="Person-Phone1" name="Person-Phone1" type="text" value="" /> </div> <div> <label for="Person-Birthday">Geboortedatum</label> <input id="Person-Birthday" name="Person-Birthday" type="date" value="" /> </div> <div> <label for="Person-Rating">Tevreden</label> <input id="Person-Rating" name="Person-Rating" type="range" value="" /> </div> </fieldset> <div class="feedback"></div> </div> <aside class="list"> <table></table> </aside> </form>
- In de
- Om de persoon in de tabel te kunnen inserten passen we de
InsertOne
methode in dePersonController
aan:[HttpPost] public IActionResult InsertOne(Models.FricFrac.Person person) { ViewBag.Message = "Insert een persoon in de database"; dbContext.Person.Add(person); dbContext.SaveChanges(); return View("Index", dbContext.Person); }
- In de
Person/UpdatingOne
view moeten we de keuzelijst ook opvullen met de landen uit deCountry
tabel. Maar er komt iets extra bij: in het keuzeveld moet de naam van het opgegeven land komen te staan:- We beginnen met de methode
UpdatingOne
vanPersonController
aan te passen. We zoeken de gegevens de te updaten persoon op en halen alle landen op:public IActionResult UpdatingOne(int? id) { ViewBag.Title = "Fric-frac Person Updating One"; if (id == null) { return NotFound(); } var person = dbContext.Person.SingleOrDefault(m => m.Id == id); if (person == null) { return NotFound(); } person.Country = dbContext.Country.SingleOrDefault(m => m.Id == person.CountryId); ViewBag.Countries = dbContext.Country.ToList(); return View(person); }
- We passen vervolgens de
UpdatingOne
view aan. Let erop hoe we de geboortedatum formatteren:@model FricFrac.Models.FricFrac.Person @{ Layout = "~/Views/Shared/MasterLayout.cshtml"; } <nav class="control-panel"> <a href="/Home/Index" class="tile"> <span class="icon-menu2"></span> <span class="screen-reader-text">Home</span> </a> <h1>Fric-frac</h1> </nav> <form class="show-room entity" action="/Person/UpdateOne" method="post"> <div class="detail"> <div class="command-panel"> <h2 class="banner">Persoon</h2> <button type="submit" class="tile"> <span class="icon-disk"></span> <span class="screen-reader-text">Update One</span> </button> <a href="/Person/Cancel" class="tile"> <span class="icon-close"></span> <span class="screen-reader-text">Annuleren</span> </a> </div> <fieldset> <input type="hidden" id="Person-Id" name="Person-Id" value="@Model.Id" /> <div> <label for="Person-FirstName">Voornaam</label> <input id="Person-FirstName" name="Person-FirstName" type="text" value="@Model.FirstName" required /> </div> <div> <label for="Person-LastName">Familienaam</label> <input id="Person-LastName" name="Person-LastName" type="text" value="@Model.LastName" required /> </div> <div> <label for="Person-Email">E-mail</label> <input id="Person-Email" name="Person-Email" type="email" value="@Model.Email" /> </div> <div> <label for="Person-Address1">Adres 1</label> <input id="Person-Address1" name="Person-Address1" type="text" value="@Model.Address1" /> </div> <div> <label for="Person-Address2">Adres 2</label> <input id="Person-Address2" name="Person-Address2" type="text" value="@Model.Address2" /> </div> <div> <label for="Person-PostalCode">Postcode</label> <input id="Person-PostalCode" name="Person-PostalCode" type="text" value="@Model.PostalCode" /> </div> <div> <label for="Person-City">Stad</label> <input id="Person-City" name="Person-City" type="text" value="@Model.City" /> </div> <div> <label for="Person-CountryId">Land</label> <select id="Person-CountryId" name="Person-CountryId"> @foreach (var item in ViewBag.Countries) { <option value="@item.Id" selected="@(item.Id == Model.CountryId ? true : false)"> @item.Name </option> } </select> </div> <div> <label for="Person-Phone1">Telefoon</label> <input id="Person-Phone1" name="Person-Phone1" type="text" value="@Model.Phone1" /> </div> <div> <label for="Person-Birthday">Geboortedatum</label> <input id="Person-Birthday" name="Person-Birthday" type="date" value="@Model.Birthday.Value.ToString("yyyy-MM-dd")" /> </div> </fieldset> <div class="feedback"></div> </div> <aside class="list"> <table></table> </aside> </form>
- We beginnen met de methode
- We passen de
UpdateOne
methode in dePersonController
aan om de wijzigingen naar de tabel weg te schrijven:[HttpPost] public IActionResult UpdateOne(Models.FricFrac.Person person) { if (ModelState.IsValid) { try { dbContext.Update(person); dbContext.SaveChanges(); return RedirectToAction("Index"); } catch (DbUpdateConcurrencyException) { if (!dbContext.Person.Any(e => e.Id == person.Id)) { return NotFound(); } else { throw; } } } return View("Index", dbContext.Person); }
- De
Cancel
methode van dePersonController
:public IActionResult Cancel() { return RedirectToAction("Index"); }
- En tenslotte voegen we voor de volledigheid nog de DeleteOne methode toe in de PersonController:
public IActionResult DeleteOne(int? id) { if (id == null) { return NotFound(); } var person = dbContext.Person.SingleOrDefault(m => m.Id == id); if (person == null) { return NotFound(); } dbContext.Person.Remove(person); dbContext.SaveChanges(); // keer terug naar de index pagina return RedirectToAction("Index"); }
2018-01-28 15:16:11